-
Notifications
You must be signed in to change notification settings - Fork 157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The case of the missing ada #1598
Conversation
This commit reworks the "preservation of ADA" test to more accurately reflect what it's testing (CHAIN level rather than NEWEPOCH). In addition, it adds an extra ada preservation property, which confirms that outside of an epoch boundary, the change in rewards is equal to the sum of withdrawls.
This will fix the problem, but does not reveal the underlying cause.
This commit fixes the underlying issue behind the missing ADA. When we create a reward update, we only grant rewards to registered stake keys. However, it's possible to deregister them after the update is created but before it's applied. In such a case, `applyRUpd` was adding them to a reward map anyway. When the key got re-registered, the reward account was being reset to 0, and hence money was being destroyed. This commit adds a check to `applyRUpd` that verifies whether a key is still registered and, if not, returns the funds to the reserves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BRAVO!
@@ -222,6 +232,7 @@ delegationTransition = do | |||
-- note that pattern match is used instead of regCred, as in the spec | |||
-- hk ∉ dom (_stkCreds ds) -- Specification code translates below | |||
not (haskey hk (_stkCreds ds)) ?! StakeKeyAlreadyRegisteredDELEG hk | |||
not (haskey (RewardAcnt network hk) (_rewards ds)) ?! StakeKeyInRewardsDELEG hk |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
want to add this change to the spec too? I can do it if that would be helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this change isn't too important (it's a sanity check), but if you felt like adding the applyRUpd
changes to the spec that would be great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👏 👏 🕵️
A fun one, this.
The scenario:
In one of our tests, 163,000 ADA vanished, violating the preservation of ADA property. How did this happen? The sequence of events was something like this:
_rewards
map, but not the_stkCreds
map._stkCreds
map, this is allowed. However, the registration zeros its rewards, resulting in the destruction of those 163,000 ADA.Why did we not spot this sooner? Well, because previously we had:
during certificate registration. But during the performance upgrades (in d716ad) this was changes to
_rewards = addpair (RewardAcnt network hk) (Coin 0) (_rewards ds),
Union is left-biased, and hence will not overwrite. addpair is implemented to ignore the old value and overwrite it with the new. Hence before d716ad, the reward account still contained funds, albeit inaccessible ones.
This PR does a number of things:
stkCreds
andrewards
maps stay in sync (e.g. that they have the same domain).rewards
.applyRUpd
by checking whether the keys are still registered. Any funds allocated to deregistered keys are now returned to the reserves.